Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

295
Visualizações
¿Algún compilador para JVM usa el goto "ancho"?

Me imagino que la mayoría de ustedes saben que goto es una palabra clave reservada en el lenguaje Java pero que en realidad no se usa. Y probablemente también sepa que goto es un código de operación de Java Virtual Machine (JVM). Considero que todas las estructuras de flujo de control sofisticadas de Java, Scala y Kotlin están, a nivel de JVM, implementadas usando alguna combinación de goto e ifeq , ifle , iflt , etc.

Mirando la especificación JVM https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.goto_w Veo que también hay un código de operación goto_w . Mientras que goto toma un desplazamiento de rama de 2 bytes, goto_w toma un desplazamiento de rama de 4 bytes. La especificación establece que

Aunque la instrucción goto_w toma un desplazamiento de rama de 4 bytes, otros factores limitan el tamaño de un método a 65535 bytes (§4.11). Este límite puede aumentar en una versión futura de Java Virtual Machine.

Me parece que goto_w está preparado para el futuro, como algunos de los otros códigos de *_w . Pero también se me ocurre que tal vez goto_w podría usarse con los dos bytes más significativos puestos a cero y los dos bytes menos significativos igual que para goto , con los ajustes necesarios.

Por ejemplo, dado este Java Switch-Case (o Scala Match-Case):

 12: lookupswitch { 112785: 48 // case "red" 3027034: 76 // case "green" 98619139: 62 // case "blue" default: 87 } 48: aload_2 49: ldc #17 // String red 51: invokevirtual #18 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 54: ifeq 87 57: iconst_0 58: istore_3 59: goto 87 62: aload_2 63: ldc #19 // String green 65: invokevirtual #18 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 68: ifeq 87 71: iconst_1 72: istore_3 73: goto 87 76: aload_2 77: ldc #20 // String blue 79: invokevirtual #18 // etc.

Podríamos reescribirlo como

 12: lookupswitch { 112785: 48 3027034: 78 98619139: 64 default: 91 } 48: aload_2 49: ldc #17 // String red 51: invokevirtual #18 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 54: ifeq 91 // 00 5B 57: iconst_0 58: istore_3 59: goto_w 91 // 00 00 00 5B 64: aload_2 65: ldc #19 // String green 67: invokevirtual #18 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 70: ifeq 91 73: iconst_1 74: istore_3 75: goto_w 91 79: aload_2 81: ldc #20 // String blue 83: invokevirtual #18 // etc.

En realidad, no he probado esto, ya que probablemente cometí un error al cambiar los "números de línea" para acomodar los goto_w s. Pero como está en la especificación, debería ser posible hacerlo.

Mi pregunta es si hay una razón por la que un compilador u otro generador de código de bytes podría usar goto_w con el límite actual de 65535 que no sea para mostrar que se puede hacer.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

El tamaño del código del método puede ser tan grande como 64K.

El desplazamiento de rama del goto corto es un entero de 16 bits con signo: de -32768 a 32767.

Por lo tanto, el desplazamiento corto no es suficiente para dar un salto desde el principio del método de 65K hasta el final.

Incluso javac a veces emite goto_w . Aquí hay un ejemplo:

 public class WideGoto { public static void main(String[] args) { for (int i = 0; i < 1_000_000_000; ) { i += 123456; // ... repeat 10K times ... } } }

Descompilando con javap -c :

 public static void main(java.lang.String[]); Code: 0: iconst_0 1: istore_1 2: iload_1 3: ldc #2 5: if_icmplt 13 8: goto_w 50018 // <<< Here it is! A jump to the end of the loop ...
over 4 years ago · Santiago Trujillo Relatório

0

No hay razón para usar goto_w cuando la rama se ajusta a un goto . Pero parece que te has perdido que las ramas son relativas , usando un desplazamiento firmado, ya que una rama también puede ir hacia atrás.

No lo nota cuando mira la salida de una herramienta como javap , ya que calcula la dirección de destino absoluta resultante antes de imprimir.

Por lo tanto, el rango de -327678 … +32767‬ de goto no siempre es suficiente para abordar cada ubicación de destino posible en el rango de 0 … +65535 .

Por ejemplo, el siguiente método tendrá una instrucción goto_w al principio:

 public static void methodWithLargeJump(int i) { for(; i == 0;) { try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1: } } } } } } } } } } } } } } } } } } } } } } static void x() {}

Demostración en Ideone

 Compiled from "Main.java" class LargeJump { public static void methodWithLargeJump(int); Code: 0: iload_0 1: ifeq 9 4: goto_w 57567 …
over 4 years ago · Santiago Trujillo Relatório

0

Parece que en algunos compiladores (probado en 1.6.0 y 11.0.7), si un método es lo suficientemente grande como para necesitar goto_w, usa exclusivamente goto_w. Incluso cuando tiene saltos muy locales, todavía usa goto_w.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda